Support controlled multi-install for safe AI agent integrations#2389
Support controlled multi-install for safe AI agent integrations#2389PascalThuet wants to merge 19 commits intogithub:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds controlled support for installing multiple AI agent integrations in a single Spec Kit project while keeping one explicit default integration, including state/schema migration and CLI workflows to manage the default without uninstalling others.
Changes:
- Introduces schema-v1 integration state (
default_integration,installed_integrations,integration_settings) with legacy compatibility, plus runtime helpers to resolve options/separators consistently. - Adds/updates integration commands to support multi-install (
install,uninstall,switch,upgrade, newuse) and keeps shared templates aligned with the default integration. - Expands registry/subcommand tests and updates docs, including surfacing “multi-install safe” status and declaring several built-in integrations safe.
Show a summary per file
| File | Description |
|---|---|
src/specify_cli/__init__.py |
Updates integration command orchestration for multi-install state, new use, and shared-template alignment. |
src/specify_cli/integration_state.py |
Adds schema-v1 normalization + persistence for multi-install integration state (legacy-compatible). |
src/specify_cli/integration_runtime.py |
Adds helpers for resolving stored/CLI options and invoke separators per integration. |
src/specify_cli/shared_infra.py |
Extracts shared infra install/refresh and preserves speckit.manifest.json across operations. |
src/specify_cli/integrations/base.py |
Adds multi_install_safe flag to declare safe multi-install integrations. |
src/specify_cli/integrations/auggie/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/claude/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/codebuddy/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/codex/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/cursor_agent/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/gemini/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/iflow/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/junie/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/kilocode/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/kimi/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/qodercli/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/qwen/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/roo/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/shai/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/tabnine/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/trae/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/windsurf/__init__.py |
Marks integration as multi_install_safe. |
tests/integrations/test_integration_subcommand.py |
Adds coverage for multi-install flows, use, shared-template refresh behavior, and manifest preservation. |
tests/integrations/test_integration_catalog.py |
Updates expected error messaging to reflect multi-install semantics (“not installed”). |
tests/integrations/test_registry.py |
Adds contract tests ensuring multi_install_safe integrations have isolated paths and disjoint manifests. |
docs/reference/integrations.md |
Documents multi-install model, new use command, safety rules, and safe integration list. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (1)
src/specify_cli/init.py:2545
- In the
target in installed_keysbranch,forceis passed asrefresh_templates_force, meaningintegration switch --forceoverwrites shared templates even though--forceis documented (via option help) as only forcing removal of modified files during uninstall. Consider aligning the flag semantics/documentation (e.g., update the help text or split into distinct flags) so--forcebehavior is not surprising when no uninstall occurs.
installed_keys,
raw_options=raw_options,
parsed_options=parsed_options,
refresh_templates_force=force,
)
- Files reviewed: 26/26 changed files
- Comments generated: 3
There was a problem hiding this comment.
Pull request overview
This PR adds controlled support for installing multiple AI agent integrations in one Spec Kit project while keeping a single explicit default integration, including state/schema migration for legacy .specify/integration.json.
Changes:
- Introduces normalized multi-install integration state (
default_integration,installed_integrations,integration_settings, schema v1) plus runtime helpers. - Adds
specify integration use <key> [--force]and updatesinstall/uninstall/switch/upgrade/listto understand multiple installed integrations and keep shared templates aligned to the default. - Declares a set of built-in integrations as
multi_install_safe, adds isolation/manifest contract tests, and updates docs + CLI output to expose safety status.
Show a summary per file
| File | Description |
|---|---|
src/specify_cli/__init__.py |
Updates integration CLI orchestration for multi-install state, adds integration use, and aligns shared infra/template behavior to the default integration. |
src/specify_cli/integration_state.py |
New module for schema v1 normalization, legacy compatibility, and persistence of .specify/integration.json. |
src/specify_cli/integration_runtime.py |
New module for resolving stored vs CLI integration options and persisted invocation separator/script settings. |
src/specify_cli/shared_infra.py |
New module to install/refresh shared scripts/templates and preserve/merge speckit.manifest.json across installs. |
src/specify_cli/integrations/base.py |
Adds multi_install_safe flag and documents the contract for safe multi-install integrations. |
src/specify_cli/integrations/claude/__init__.py |
Marks Claude integration as multi-install safe. |
src/specify_cli/integrations/codex/__init__.py |
Marks Codex integration as multi-install safe. |
src/specify_cli/integrations/cursor_agent/__init__.py |
Marks Cursor Agent integration as multi-install safe. |
src/specify_cli/integrations/gemini/__init__.py |
Marks Gemini integration as multi-install safe. |
src/specify_cli/integrations/tabnine/__init__.py |
Marks Tabnine integration as multi-install safe. |
src/specify_cli/integrations/auggie/__init__.py |
Marks Auggie integration as multi-install safe. |
src/specify_cli/integrations/codebuddy/__init__.py |
Marks Codebuddy integration as multi-install safe. |
src/specify_cli/integrations/iflow/__init__.py |
Marks Iflow integration as multi-install safe. |
src/specify_cli/integrations/junie/__init__.py |
Marks Junie integration as multi-install safe. |
src/specify_cli/integrations/kilocode/__init__.py |
Marks Kilocode integration as multi-install safe. |
src/specify_cli/integrations/kimi/__init__.py |
Marks Kimi integration as multi-install safe. |
src/specify_cli/integrations/qodercli/__init__.py |
Marks Qoder CLI integration as multi-install safe. |
src/specify_cli/integrations/qwen/__init__.py |
Marks Qwen integration as multi-install safe. |
src/specify_cli/integrations/roo/__init__.py |
Marks Roo integration as multi-install safe. |
src/specify_cli/integrations/shai/__init__.py |
Marks Shai integration as multi-install safe. |
src/specify_cli/integrations/trae/__init__.py |
Marks Trae integration as multi-install safe. |
src/specify_cli/integrations/windsurf/__init__.py |
Marks Windsurf integration as multi-install safe. |
tests/integrations/test_registry.py |
Adds registry-level isolation contracts + pairwise manifest-disjointness tests for safe integrations. |
tests/integrations/test_integration_subcommand.py |
Adds CLI tests covering multi-safe installs, legacy migration, use, uninstall behavior, and default-template alignment. |
tests/integrations/test_integration_catalog.py |
Updates assertions for new “not installed” messaging under multi-install semantics. |
tests/integrations/test_cli.py |
Adds coverage for warning when shared manifest is unreadable before recreating it. |
docs/reference/integrations.md |
Documents multi-install model, safety rules, use command, and updated semantics for install/switch/upgrade/list. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 27/27 changed files
- Comments generated: 3
mnriem
left a comment
There was a problem hiding this comment.
Please address Copilot feedback. If not applicable, please explain why
There was a problem hiding this comment.
Pull request overview
Adds a controlled multi-install model for Spec Kit AI agent integrations, enabling multiple installed integrations per project while keeping one explicit default and keeping shared templates aligned to that default.
Changes:
- Introduces normalized integration state (
default_integration,installed_integrations,integration_settings,integration_state_schema) with legacy compatibility. - Adds runtime/shared-infra helpers to refresh shared templates safely and preserve/merge the shared
speckit.manifest.json. - Expands CLI + docs + tests to support multi-install safety declarations and the new
specify integration useworkflow.
Show a summary per file
| File | Description |
|---|---|
| tests/integrations/test_registry.py | Adds contracts/tests enforcing isolation + disjoint manifests for multi_install_safe integrations. |
| tests/integrations/test_integration_subcommand.py | Adds CLI behavior tests for multi-install, use, shared template refresh, and list output. |
| tests/integrations/test_integration_state.py | Adds unit tests for integration-state normalization and persistence. |
| tests/integrations/test_integration_catalog.py | Updates expectation to reflect “not installed” semantics under multi-install. |
| tests/integrations/test_cli.py | Adds coverage for warning/fallback when the shared manifest is unreadable. |
| src/specify_cli/shared_infra.py | New module to install/refresh shared scripts/templates while preserving shared manifest history. |
| src/specify_cli/integration_state.py | New module for state normalization, schema defaults, deduping, and JSON persistence. |
| src/specify_cli/integration_runtime.py | New module to resolve/stash per-integration options and invocation separator. |
| src/specify_cli/init.py | Wires multi-install logic into install/uninstall/switch/upgrade/list, adds integration use, and delegates shared infra. |
| docs/reference/integrations.md | Documents multi-install model, use, --force behavior updates, and safe-integration list. |
| src/specify_cli/integrations/base.py | Introduces multi_install_safe flag and documents its isolation contract. |
| src/specify_cli/integrations/auggie/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/claude/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/codex/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/cursor_agent/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/gemini/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/iflow/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/junie/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/kilocode/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/kimi/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/qodercli/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/qwen/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/roo/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/shai/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/tabnine/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/trae/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/windsurf/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/codebuddy/init.py | Marks integration as multi_install_safe. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 28/28 changed files
- Comments generated: 3
There was a problem hiding this comment.
Pull request overview
Adds controlled multi-install support for AI agent integrations in Spec Kit projects by introducing a normalized integration state model, a use subcommand to switch defaults non-destructively, and “multi-install safe” contracts/tests to gate automatic co-installs.
Changes:
- Introduces integration state/runtime/shared-infra helper modules and updates CLI orchestration to support multiple installed integrations with a single default.
- Adds
specify integration use <key>(+--force) and updatesinstall/uninstall/switch/upgrade/listbehaviors for multi-install. - Declares multiple built-in integrations as
multi_install_safe, adds registry-level safety contract tests, and updates docs/output to surface safety status.
Show a summary per file
| File | Description |
|---|---|
| tests/integrations/test_registry.py | Adds registry-level contract tests to enforce multi-install-safe isolation (paths/context/manifests). |
| tests/integrations/test_integration_subcommand.py | Expands CLI subcommand tests for multi-install flows, new use command, and list output. |
| tests/integrations/test_integration_state.py | Adds unit tests for integration state normalization/persistence helpers. |
| tests/integrations/test_integration_catalog.py | Updates error expectation to reflect “not installed” semantics under multi-install. |
| tests/integrations/test_cli.py | Adds coverage for warnings when the shared infra manifest is unreadable/invalid encoding. |
| src/specify_cli/shared_infra.py | New module to install/refresh shared templates/scripts while preserving and merging a shared manifest. |
| src/specify_cli/integration_state.py | New module to normalize/persist .specify/integration.json with legacy compatibility and schema versioning. |
| src/specify_cli/integration_runtime.py | New module to resolve per-integration stored options/settings and invocation separator behavior. |
| src/specify_cli/init.py | Refactors CLI orchestration to use new helpers; implements multi-install logic, use, and default-aligned shared templates. |
| src/specify_cli/integrations/base.py | Adds multi_install_safe flag to the integration base contract. |
| src/specify_cli/integrations/claude/init.py | Declares Claude integration as multi-install safe. |
| src/specify_cli/integrations/codex/init.py | Declares Codex integration as multi-install safe. |
| src/specify_cli/integrations/cursor_agent/init.py | Declares Cursor Agent integration as multi-install safe. |
| src/specify_cli/integrations/gemini/init.py | Declares Gemini integration as multi-install safe. |
| src/specify_cli/integrations/iflow/init.py | Declares Iflow integration as multi-install safe. |
| src/specify_cli/integrations/junie/init.py | Declares Junie integration as multi-install safe. |
| src/specify_cli/integrations/kilocode/init.py | Declares Kilocode integration as multi-install safe. |
| src/specify_cli/integrations/kimi/init.py | Declares Kimi integration as multi-install safe. |
| src/specify_cli/integrations/qodercli/init.py | Declares Qoder CLI integration as multi-install safe. |
| src/specify_cli/integrations/qwen/init.py | Declares Qwen integration as multi-install safe. |
| src/specify_cli/integrations/roo/init.py | Declares Roo integration as multi-install safe. |
| src/specify_cli/integrations/shai/init.py | Declares Shai integration as multi-install safe. |
| src/specify_cli/integrations/tabnine/init.py | Declares Tabnine integration as multi-install safe. |
| src/specify_cli/integrations/trae/init.py | Declares Trae integration as multi-install safe. |
| src/specify_cli/integrations/windsurf/init.py | Declares Windsurf integration as multi-install safe. |
| src/specify_cli/integrations/auggie/init.py | Declares Auggie integration as multi-install safe. |
| src/specify_cli/integrations/codebuddy/init.py | Declares Codebuddy integration as multi-install safe. |
| docs/reference/integrations.md | Updates reference docs for multi-install behavior, use, and safety model/output. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (2)
src/specify_cli/init.py:2635
- In
integration switch, theIntegrationManifest.load(...)calls can raiseUnicodeDecodeErrorfor non-UTF-8 manifests (andOSErrorfor IO issues), but the current exception handling only catchesValueError/FileNotFoundError. This can lead to an unhandled exception/traceback for a corrupt manifest; consider catching decode/IO errors and showing the same recovery guidance/warning instead.
raise typer.Exit(1)
# Clear metadata so a failed Phase 2 doesn't leave stale references
src/specify_cli/init.py:2804
IntegrationManifest.load(...)can raiseUnicodeDecodeErrorwhen the manifest file isn't UTF-8 (andOSErrorfor IO issues), but the upgrade path's error handling only catchesValueError/FileNotFoundError. Consider catching decode/IO failures too sointegration upgradefails gracefully with a clear recovery message instead of raising an unhandled exception.
console.print("\nUse [cyan]--force[/cyan] to overwrite modified files, or resolve manually.")
raise typer.Exit(1)
- Files reviewed: 28/28 changed files
- Comments generated: 2
|
Please address Copilot feedback. If not applicable, please explain why Be aware that everyone has to go through this same cycle of relentless Copilot feedback, maintainers included |
There was a problem hiding this comment.
Pull request overview
This PR adds multi-install support for AI agent integrations in Spec Kit projects by introducing a richer integration state model (default + multiple installed), a new specify integration use command, and shared-infra behavior that keeps shared templates aligned with the current default integration.
Changes:
- Introduces normalized integration state (
default_integration,installed_integrations, per-integration settings, schema version) with legacy compatibility. - Adds
integration useand updatesinstall/uninstall/switch/upgrade/listto work with multiple installed integrations and multi-install safety rules. - Adds shared-infra helpers + tests enforcing multi-install-safe isolation and manifest disjointness.
Show a summary per file
| File | Description |
|---|---|
src/specify_cli/__init__.py |
CLI orchestration updated for multi-install state, new use command, and shared template alignment logic. |
src/specify_cli/integration_state.py |
New normalization + persistence helpers for multi-install integration state (legacy compatible). |
src/specify_cli/integration_runtime.py |
New helpers for resolving/storing per-integration runtime options and invocation separators. |
src/specify_cli/shared_infra.py |
New shared scripts/templates install + “refresh templates” logic with shared manifest preservation. |
src/specify_cli/integrations/base.py |
Adds multi_install_safe flag on integrations. |
src/specify_cli/integrations/*/__init__.py |
Marks a set of integrations as multi_install_safe=True. |
tests/integrations/test_registry.py |
Adds registry-level contracts ensuring safe integrations have isolated paths and disjoint manifests. |
tests/integrations/test_integration_subcommand.py |
Expands CLI behavior coverage for multi-install flows (install/use/switch/uninstall/upgrade). |
tests/integrations/test_integration_state.py |
New unit tests for state normalization and persistence helpers. |
tests/integrations/test_integration_catalog.py |
Updates expected error messaging for upgrade on non-installed integrations. |
tests/integrations/test_cli.py |
Adds coverage for shared manifest read/encoding failure warnings. |
docs/reference/integrations.md |
Documents multi-install behavior, use, safety model, and safe integrations list. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (1)
src/specify_cli/shared_infra.py:166
install_shared_infra()may overwrite files viashutil.copy2()/dst.write_text()even when the destination path is a symlink. That can be abused for arbitrary file overwrite outside the repo if.specify/scripts/...or.specify/templates/...contains symlinks. Please add a symlink check (skip unless explicitly handled) and ensure the resolved destination stays withinproject_pathbefore writing.
dst_path.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(src_path, dst_path)
rel = dst_path.relative_to(project_path).as_posix()
manifest.record_existing(rel)
templates_src = shared_templates_source(core_pack=core_pack, repo_root=repo_root)
if templates_src.is_dir():
dest_templates = project_path / ".specify" / "templates"
dest_templates.mkdir(parents=True, exist_ok=True)
for src in templates_src.iterdir():
if not src.is_file() or src.name == "vscode-settings.json" or src.name.startswith("."):
continue
dst = dest_templates / src.name
if dst.exists() and not force:
skipped_files.append(str(dst.relative_to(project_path)))
continue
content = src.read_text(encoding="utf-8")
content = IntegrationBase.resolve_command_refs(content, invoke_separator)
dst.write_text(content, encoding="utf-8")
rel = dst.relative_to(project_path).as_posix()
manifest.record_existing(rel)
- Files reviewed: 28/28 changed files
- Comments generated: 1
|
Please address Copilot feedback. Note somethings things like this come up as part of the review because code around it gets touched / same file gets touched and somehow Copilot missed it the first go around. |
mnriem
left a comment
There was a problem hiding this comment.
Please address Copilot feedback. Down to one comment!
There was a problem hiding this comment.
Pull request overview
This PR adds controlled multi-install support for AI agent integrations in Spec Kit projects, keeping a single explicit default integration while allowing additional safe integrations to coexist.
Changes:
- Introduces normalized multi-install integration state (
default_integration,installed_integrations, per-integration settings, schema versioning) with legacy compatibility. - Adds/updates CLI behaviors to support multi-install installs, default switching via
integration use, and safer shared-infra/template management (including symlink refusal and shared manifest preservation). - Expands integration registry contracts and CLI tests to enforce multi-install safety invariants and validate new flows.
Show a summary per file
| File | Description |
|---|---|
| tests/test_presets.py | Filters an expected self-test preset warning to keep preset tests stable. |
| tests/integrations/test_registry.py | Adds contract tests ensuring multi_install_safe integrations have isolated paths and disjoint manifests. |
| tests/integrations/test_integration_subcommand.py | Extends subcommand tests for multi-install behavior, use, updated error messaging, and manifest unreadability cases. |
| tests/integrations/test_integration_state.py | Adds unit tests for integration state normalization and persistence helpers. |
| tests/integrations/test_integration_catalog.py | Updates expected CLI error text for upgrade when key is not installed. |
| tests/integrations/test_cli.py | Adds coverage for shared-infra manifest warnings and symlinked destination refusal. |
| src/specify_cli/shared_infra.py | New shared-infra module: shared manifest lifecycle, safe writes (symlink/escape refusal), and template refresh logic. |
| src/specify_cli/integration_state.py | New module for integration state normalization, legacy compatibility, and writing .specify/integration.json. |
| src/specify_cli/integration_runtime.py | New module to resolve per-integration options/settings and compute invocation separators. |
| src/specify_cli/init.py | Updates CLI orchestration to support multi-install state, integration use, safer shared infra, and revised install/switch/upgrade/uninstall flows. |
| src/specify_cli/integrations/base.py | Adds the multi_install_safe flag and documents the safety contract. |
| src/specify_cli/integrations/auggie/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/claude/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/codebuddy/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/codex/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/cursor_agent/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/gemini/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/iflow/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/junie/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/kilocode/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/kimi/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/qodercli/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/qwen/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/roo/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/shai/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/tabnine/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/trae/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/windsurf/init.py | Marks integration as multi_install_safe. |
| docs/reference/integrations.md | Documents multi-install semantics, use, updated switch/upgrade/install behavior, and declared safe integrations. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 29/29 changed files
- Comments generated: 1
There was a problem hiding this comment.
Pull request overview
Adds first-class, backward-compatible support for multiple installed AI agent integrations per Spec Kit project while keeping a single explicit default integration, plus shared-infra/template handling that stays aligned to the default integration’s invocation style.
Changes:
- Introduces normalized multi-install integration state (
default_integration,installed_integrations, per-integrationintegration_settings, schema v1) and a newspecify integration use <key>command. - Adds controlled multi-install behavior gated by
multi_install_safe(or explicit--force) and updates install/switch/upgrade/uninstall/list flows accordingly. - Refactors shared infrastructure install/refresh into a dedicated module and expands test coverage for multi-install contracts and symlink/manifest failure modes.
Show a summary per file
| File | Description |
|---|---|
| tests/test_presets.py | Suppresses an intentional self-test preset warning to keep preset tests stable. |
| tests/integrations/test_registry.py | Adds registry-level contract tests for multi_install_safe isolation (paths + disjoint manifests). |
| tests/integrations/test_integration_subcommand.py | Expands CLI lifecycle tests for multi-install, use, safety gating, and failure/rollback behavior. |
| tests/integrations/test_integration_state.py | Adds unit tests for integration-state normalization and persistence helpers. |
| tests/integrations/test_integration_catalog.py | Updates expected error messaging for “not installed” semantics. |
| tests/integrations/test_cli.py | Adds shared-infra tests for unreadable manifests and symlink refusal behavior. |
| src/specify_cli/shared_infra.py | New shared infrastructure installer/refresher with manifest preservation and destination safety checks. |
| src/specify_cli/integrations/windsurf/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/trae/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/tabnine/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/shai/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/roo/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/qwen/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/qodercli/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/kimi/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/kilocode/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/junie/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/iflow/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/gemini/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/cursor_agent/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/codex/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/codebuddy/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/claude/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integrations/base.py | Introduces multi_install_safe flag and documents its invariants. |
| src/specify_cli/integrations/auggie/init.py | Marks integration as multi_install_safe. |
| src/specify_cli/integration_state.py | New helpers for state normalization, legacy compatibility, and JSON persistence. |
| src/specify_cli/integration_runtime.py | New helpers for resolving options/settings and invoke-separator behavior. |
| src/specify_cli/init.py | Updates Typer integration commands to support multi-install state, use, safe multi-install gating, and shared infra refactor. |
| docs/reference/integrations.md | Documents multi-install behavior, use, safety model, and updated semantics for install/switch/upgrade. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 29/29 changed files
- Comments generated: 2
|
Please address Copilot feedback. If not applicable, please explain why |
There was a problem hiding this comment.
Pull request overview
This PR adds controlled multi-install support for AI agent integrations in Spec Kit projects by expanding integration state tracking, introducing a non-destructive default-integration switch (integration use), and hardening shared-infrastructure installation.
Changes:
- Introduces normalized multi-install integration state (
default_integration,installed_integrations,integration_settings, schema) with legacy compatibility. - Adds/updates integration subcommands (
use, updatedinstall/switch/upgrade/list/uninstall) to support multiple installed integrations while keeping one default. - Moves shared scripts/templates lifecycle into
shared_infra.pywith stronger safety checks (symlink/escape refusal) and improved manifest handling.
Show a summary per file
| File | Description |
|---|---|
src/specify_cli/__init__.py |
Updates Typer integration commands to support multi-install/default switching and routes shared infra operations through new helpers. |
src/specify_cli/integration_state.py |
Adds normalization + persistence helpers for the new integration state model (schema v1 + legacy alias). |
src/specify_cli/integration_runtime.py |
Adds helpers for resolving/storing per-integration options and invocation separator. |
src/specify_cli/shared_infra.py |
New shared infra installer/refresh logic with manifest preservation and symlink/path-escape protections. |
src/specify_cli/integrations/base.py |
Adds multi_install_safe contract flag on integrations. |
src/specify_cli/integrations/*/__init__.py |
Marks selected integrations as multi_install_safe=True. |
tests/integrations/test_registry.py |
Adds registry-level contract tests ensuring safe integrations are isolated and manifests are disjoint. |
tests/integrations/test_integration_subcommand.py |
Adds CLI tests for multi-install flows, use, schema rejection, and manifest error handling. |
tests/integrations/test_integration_state.py |
Adds unit tests for state normalization and persistence behavior. |
tests/integrations/test_cli.py |
Adds tests for shared infra manifest fallback warnings and symlink/path safety preflights. |
tests/test_presets.py |
Filters an expected warning during self-test preset installation to reduce test noise. |
tests/integrations/test_integration_catalog.py |
Updates error expectations for “not installed” semantics. |
docs/reference/integrations.md |
Documents multi-install behavior, use, updated switch/upgrade, and safe integration list. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 29/29 changed files
- Comments generated: 1
|
Please address Copilot feedback. Thank you for working so diligently through these! |
There was a problem hiding this comment.
Pull request overview
Adds multi-install support for AI agent integrations while preserving a single explicit default integration, and hardens shared infra/template installation to be safer and stateful.
Changes:
- Introduces normalized multi-integration state (
default_integration,installed_integrations,integration_settings, schemaing) plus a newspecify integration usecommand to switch defaults without uninstalling. - Adds a “multi-install safe” contract for integrations (enforced via registry-level pairwise tests) and a
--forceescape hatch for unsafe combinations. - Moves shared scripts/templates install/refresh into a dedicated
shared_infra.pymodule with manifest preservation and strict symlink/path preflighting.
Show a summary per file
| File | Description |
|---|---|
src/specify_cli/__init__.py |
CLI orchestration updates for multi-install state, new integration use, safer shared infra handling, and updated list/install/switch/upgrade behaviors. |
src/specify_cli/integration_state.py |
New integration-state normalization + persistence layer (schema, legacy aliasing, dedupe/strip behavior). |
src/specify_cli/integration_runtime.py |
New helpers for resolving stored integration options and invocation separators per integration. |
src/specify_cli/shared_infra.py |
New shared scripts/templates installer and template refresher with manifest preservation + symlink/path safety checks. |
src/specify_cli/integrations/base.py |
Adds multi_install_safe flag and documents its invariants. |
src/specify_cli/integrations/*/__init__.py |
Marks selected integrations as multi_install_safe=True. |
tests/integrations/test_registry.py |
Adds contract tests enforcing path/context/manifest isolation for all multi_install_safe integrations (including pairwise manifest disjointness). |
tests/integrations/test_integration_subcommand.py |
Expands CLI tests for multi-install flows, default switching (use), schema rejection, and unreadable manifest handling. |
tests/integrations/test_integration_state.py |
New unit tests for state normalization and persistence helpers. |
tests/integrations/test_cli.py |
Adds tests for shared infra manifest fallback warnings, symlink refusal, and preflight behavior. |
tests/test_presets.py |
Filters an intentional self-test preset warning to keep tests stable. |
tests/integrations/test_integration_catalog.py |
Updates assertions for new “not installed” error semantics. |
docs/reference/integrations.md |
Documents multi-install behavior, use, safety model, and lists declared safe integrations. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 29/29 changed files
- Comments generated: 0
|
Please address Test & Lint errors |
|
Hi @mnriem, all Copilot threads are now addressed and there are no active unresolved review threads left. The latest pushed commit is The current merge block appears to be:
Could you please approve/run the workflows and re-review or clear the stale change request when you have a chance? |
There was a problem hiding this comment.
Pull request overview
This PR implements controlled multi-install support for AI agent integrations in Spec Kit projects, enabling multiple integrations to coexist while maintaining one explicit default integration and keeping shared templates aligned to that default.
Changes:
- Introduces a new integration state model (
default_integration,installed_integrations,integration_settings,integration_state_schema) with legacy compatibility for theintegrationfield. - Adds
specify integration use <key>(and--force) to switch the default integration without uninstalling others, and updates install/switch/upgrade/uninstall/list flows for multi-install behavior. - Extracts shared script/template management into
shared_infra.pywith stronger safety checks (symlink/path preflight) and updates tests/docs accordingly.
Show a summary per file
| File | Description |
|---|---|
src/specify_cli/__init__.py |
Updates CLI orchestration to support multi-install state, adds integration use, and routes shared infra operations through the new shared infra module. |
src/specify_cli/integration_state.py |
New module for integration state normalization/persistence and legacy compatibility. |
src/specify_cli/integration_runtime.py |
New module for resolving per-integration runtime options/settings and invoke separator behavior. |
src/specify_cli/shared_infra.py |
New module for shared scripts/templates install/refresh, manifest loading/merging, and safety validation. |
src/specify_cli/integrations/base.py |
Adds the multi_install_safe contract flag to integrations. |
src/specify_cli/integrations/auggie/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/claude/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/codebuddy/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/codex/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/cursor_agent/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/gemini/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/iflow/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/junie/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/kilocode/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/kimi/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/qodercli/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/qwen/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/roo/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/shai/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/tabnine/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/trae/__init__.py |
Marks integration as multi_install_safe. |
src/specify_cli/integrations/windsurf/__init__.py |
Marks integration as multi_install_safe. |
tests/integrations/test_integration_state.py |
Adds unit tests for normalization/cleaning of integration state. |
tests/integrations/test_integration_subcommand.py |
Expands CLI tests for list/install/uninstall/use/switch/upgrade under multi-install state. |
tests/integrations/test_registry.py |
Adds contract tests validating isolation requirements for multi_install_safe integrations. |
tests/integrations/test_cli.py |
Adds coverage for shared infra manifest fallback warnings and symlink/path preflight safety. |
tests/integrations/test_integration_catalog.py |
Aligns upgrade error messaging expectations with “not installed” semantics. |
tests/test_presets.py |
Filters expected warning during self-test preset install to keep tests stable. |
docs/reference/integrations.md |
Documents multi-install model, use, updated switch behavior, and multi_install_safe guidance. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 29/29 changed files
- Comments generated: 1
mnriem
left a comment
There was a problem hiding this comment.
I triggered the workflow and that looks good. I also triggered another Copilot review as you did do another commit. And yup one more comment. So please address that and I hope that will be the last one!
|
Hi @mnriem, the last Copilot comment has been addressed in Could you please approve/run the workflows for the latest commit and re-review or clear the stale changes-requested review? Many thanks for your patience |
Summary
Fixes #2257.
This PR adds controlled support for installing multiple AI agent integrations in the same Spec Kit project.
The goal is not to encourage multi-agent workflows by default, but to support team portability for repositories where different contributors use different agents, while keeping one explicit default integration.
What changes
default_integration,installed_integrations,integration_settings,integration_state_schema, and the legacy-compatibleintegrationfield.specify integration use <key>to change the default integration without uninstalling others.specify integration use <key> --forceto refresh managed shared templates even when they were locally modified.multi_install_safe.--forceto explicitly opt into installing integrations that are not declared safe together.install,uninstall,switch,upgrade, andlistto understand multiple installed integrations.speckit.manifest.jsoninstead of replacing it with an empty manifest during additional installs..specify/scriptsor.specify/templates.switch --integration-optionsfor already-installed targets, because changing options requires reinstalling managed files.switch <current> --forcerefresh managed shared templates instead of silently no-oping.switch --force/switch --integration-optionsdocumentation..specify/integration.jsonfiles.Architecture
integration_state.pyowns integration-state normalization, schema defaults, legacy compatibility, and JSON persistence.integration_runtime.pyowns runtime option resolution, per-integration settings, and invocation-separator lookup.shared_infra.pyowns shared Spec Kit script/template installation and the sharedspeckit.manifest.jsonlifecycle.__init__.pyremains the Typer command/orchestration layer, with thin wrappers where CLI-specific dependencies such as version lookup and console output are required.Safety model
An integration is declared
multi_install_safeonly when it uses:integration_settingsThe PR includes registry-level tests that enforce these invariants for every safe integration. The tests exercise every safe integration pair in both install orders inside one parametrized case per unordered pair, validating order-sensitive manifest isolation without doubling pytest case count. The table-output test verifies representative rows directly instead of matching loose tokens.
Integrations that share context files or command directories, require dynamic install paths, or merge shared tool settings remain unsafe by default and still require
--force.Why
Today, switching integrations is destructive from a team-portability perspective: a repository can only represent one agent integration cleanly at a time.
This PR keeps the existing single-default model while allowing safe integrations to coexist. That lets a repo support, for example, both Claude Code and Codex CLI without forcing contributors to constantly uninstall and reinstall agent-specific files.
Backward compatibility
Existing projects with legacy state such as:
{ "integration": "claude" }continue to work. The state is normalized into the new model when integration commands run.
The legacy
integrationfield is still written as an alias for the default integration, and whitespace around user-edited integration keys/settings is normalized before comparisons or persistence.Testing
uvx ruff check src/specify_cli/shared_infra.py tests/integrations/test_cli.pyuv run pytest tests/integrations/test_cli.py::TestInitIntegrationFlag::test_shared_infra_refuses_symlinked_script_destination tests/integrations/test_cli.py::TestInitIntegrationFlag::test_shared_infra_refuses_symlinked_template_destination tests/integrations/test_cli.py::TestInitIntegrationFlag::test_shared_template_refresh_refuses_symlinked_destination -quvx ruff check src/specify_cli/__init__.py src/specify_cli/shared_infra.py tests/integrations/test_integration_subcommand.py tests/integrations/test_cli.pyuv run pytest tests/integrations/test_integration_subcommand.py::TestIntegrationUse::test_use_does_not_persist_default_when_template_refresh_fails tests/integrations/test_integration_subcommand.py::TestIntegrationUse::test_use_installed_integration_sets_default tests/integrations/test_cli.py::TestInitIntegrationFlag::test_shared_infra_refuses_symlinked_template_destination -quv run pytest tests/integrations/test_cli.py -quv run pytest tests/integrations/test_integration_subcommand.py tests/integrations/test_cli.py -quv run pytest tests/integrations/test_manifest.py tests/integrations/test_integration_subcommand.py -quvx ruff check tests/integrations/test_integration_state.py tests/integrations/test_integration_subcommand.pyuv run pytest tests/integrations/test_integration_state.py tests/integrations/test_integration_subcommand.py -quvx ruff check tests/test_presets.pyuv run pytest tests/test_presets.py -quvx ruff check src/specify_cli/shared_infra.py src/specify_cli/integration_state.py src/specify_cli/__init__.py tests/integrations/test_cli.py tests/integrations/test_integration_state.py tests/integrations/test_integration_subcommand.pyuv run pytest tests/integrations/test_cli.py::TestInitIntegrationFlag::test_shared_infra_refuses_symlinked_specify_directory_before_mkdir tests/integrations/test_cli.py::TestInitIntegrationFlag::test_shared_template_refresh_preflights_before_writing tests/integrations/test_cli.py::TestInitIntegrationFlag::test_shared_infra_install_preflights_before_writing tests/integrations/test_integration_state.py::test_normalize_integration_state_preserves_newer_schema tests/integrations/test_integration_subcommand.py::TestIntegrationList::test_list_rejects_newer_integration_state_schema -quv run pytest tests/integrations/test_cli.py tests/integrations/test_integration_state.py tests/integrations/test_integration_subcommand.py -quvx ruff check src/specify_cli/shared_infra.py tests/integrations/test_cli.pyuv run pytest tests/integrations/test_cli.py::TestInitIntegrationFlag::test_shared_infra_install_supports_nested_script_sources tests/integrations/test_cli.py::TestInitIntegrationFlag::test_shared_infra_install_preflights_before_writing tests/integrations/test_cli.py::TestInitIntegrationFlag::test_shared_infra_refuses_symlinked_specify_directory_before_mkdir -quv run pytest tests/integrations/test_cli.py -quvx ruff check src/specify_cli/shared_infra.py tests/integrations/test_cli.pyuv run pytest tests/integrations/test_cli.py::TestInitIntegrationFlag::test_shared_template_writes_are_not_world_writable tests/integrations/test_cli.py::TestInitIntegrationFlag::test_shared_infra_install_supports_nested_script_sources -quv run pytest tests/integrations/test_cli.py -qgit diff --checkuv run pytest -qFull suite result: